package com.dyApi.business.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dyApi.business.service.KsApiService;
import com.dyApi.utils.RedisUtils;
import com.kuaishou.locallife.open.api.client.KsLocalLifeAccessTokenClient;
import com.kuaishou.locallife.open.api.client.oauth.OAuthAccessTokenKsClient;
import com.kuaishou.locallife.open.api.KsLocalLifeApiException;
import com.kuaishou.locallife.open.api.domain.locallife_shop.OpenApiPoiShopPoiRespData;
import com.kuaishou.locallife.open.api.domain.locallife_third_code.*;
import com.kuaishou.locallife.open.api.domain.openapi.CipherInfoRequest;
import com.kuaishou.locallife.open.api.domain.openapi.CipherInfoResponse;
import com.kuaishou.locallife.open.api.request.locallife_shop.GoodlifeV1ShopPoiQueryRequest;
import com.kuaishou.locallife.open.api.request.openapi.GoodlifeSecurityDecryptBatchRequest;
import com.kuaishou.locallife.open.api.response.locallife_shop.GoodlifeV1ShopPoiQueryResponse;
import com.kuaishou.locallife.open.api.response.oauth.KsAccessTokenPreviousVersionResponse;
import com.kuaishou.locallife.open.api.response.openapi.GoodlifeSecurityDecryptBatchResponse;
import io.netty.util.internal.StringUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
public class KsApiServiceImpl implements KsApiService {

    @Value("${ks-api.appKey}")
    private String appKey;

    @Value("${ks-api.appSecret}")
    private String appSecret;

    @Value("${ks-api.url}")
    private String ksApiUrl;

    @Value("${ks-api.refreshToken}")
    private String refreshTokenUrl;

    @Value("${ks-api.accessToken}")
    private String accessTokenUrl;

    @Value("${ks-api.accountId}")
    private String accountId;

    @Value("${ks-api.code}")
    private String code;

    @Value("${sync.url}")
    private String syncUrl;

    @Value("${sync.order}")
    private String syncOrder;

    @Value("${sync.setOrder}")
    private String setOrderUrl;

    @Value("${sync.refund}")
    private String refundUrl;

    @Autowired
    private RedisUtils redisUtils;
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Override
    public Map<String, Object> poi() {
        Map<String, Object> res = new HashMap<>();
        String accessToken = getAccessToken();
        if (StringUtils.isEmpty(accessToken)) {// token无
            return res;
        }

        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
                .setAccessToken(accessToken)
                .build();

        GoodlifeV1ShopPoiQueryRequest request = new GoodlifeV1ShopPoiQueryRequest();

        request.setAccount_id(Long.valueOf(accountId));
        request.setSize(100);
        request.setPage(1);

        try {
            GoodlifeV1ShopPoiQueryResponse response = client.execute(request);
            if (ObjectUtil.isNotEmpty(response.getData()) && response.getData().getError_code() == 0) {
                OpenApiPoiShopPoiRespData data = response.getData();
                // Create a JSON object
                JSONObject json = (JSONObject) JSON.toJSON(data);
                // Convert the JSON object to a Map
                res = (Map<String, Object>) json;
            }
        } catch (KsLocalLifeApiException e) {}

        return res;

    }

    @Override
    public Map<String, Object> orderConfirm(Map<String,Object> params) {
//        System.out.println(JSON.toJSONString(params));
        // xiangyingjieguo
        Map<String, Object> res = new HashMap<>();
        // 拼接请求服务数据
        Map<String, Object> req = new HashMap<>();
        // 基础信息
        req.put("createUserId", "12");
        req.put("orderFrom", 5);
        // 订单ID
        String orderSn = (String) params.get("order_id");
        req.put("orderSn", params.get("order_id"));

        req.put("userName", "张三");
        req.put("mobileno", 13300000000L);

        // 商品及金额信息
        Integer count = Integer.valueOf(params.get("count").toString());
        // 票务信息
        List<Map<String, Object>> tickets = new ArrayList<>();
        Map<String, Object> ticket = new HashMap<>();
        ticket.put("id",params.get("third_product_id"));
        ticket.put("buyNum", count);
        Object amount = params.get("original_amount");
        Map<String,Object> data = new HashMap<>();
        if (ObjectUtil.isEmpty(amount)) {
            data.put("error_code",20);
            data.put("description","缺少original_amount！");
            data.put("ext_order_id",orderSn);
            res.put("data", data);
            return res;
        }
        BigDecimal bCount = new BigDecimal(count + "");
        BigDecimal bAmount = new BigDecimal(amount.toString()).divide(new BigDecimal("100"), 2, RoundingMode.HALF_EVEN);
        req.put("amount", bAmount);
        BigDecimal bPrice = bAmount.divide(bCount,2, RoundingMode.HALF_EVEN);
        ticket.put("settlePrice", bPrice);
        ticket.put("buyPrice", bPrice);
        tickets.add(ticket);
        req.put("tickets", tickets);
        // 请求三方接口
        HttpResponse httpResponse = HttpRequest.post(syncUrl + syncOrder)
                .body(JSONUtil.toJsonStr(req))
                .execute();
        int status = httpResponse.getStatus(); //获取响应码
        String body = httpResponse.body(); //获取响应内容
        if (status != HttpStatus.HTTP_OK) {

            data.put("error_code",20);
            data.put("description","商户异常");
            data.put("ext_order_id",orderSn);
            res.put("data", data);

            return res;
        }
        // 响应结果
        Map<String, Object> map = JSONUtil.parseObj(body);
        if ((int) map.get("code") != 0) {
            data.put("error_code",20);
            data.put("description","商户异常");
            data.put("ext_order_id",orderSn);
            res.put("data", data);

            return res;
        }
        Map<String, Object> reqData = (Map<String, Object>)map.get("data");
        redisUtils.set(orderSn, String.valueOf(reqData.get("orderId")));
        // 成功直接返回
        data.put("error_code",0);
        data.put("description","success");
        data.put("ext_order_id",orderSn);
        res.put("data", data);

        return res;
    }

    @Override
    public Map<String, Object> setCoupon(Map<String,Object> params) {
        Map<String, Object> res = new HashMap<>();
        // 拼接请求服务数据
        Map<String, Object> req = new HashMap<>();
        String orderSn = (String) params.get("order_id");
        req.put("orderId", redisUtils.get(orderSn));
        // 请求三方接口
        HttpResponse httpResponse = HttpRequest.post(syncUrl + setOrderUrl)
                .body(JSONUtil.toJsonStr(req))
                .execute();
        Map<String,Object> data = new HashMap<>();
        int status = httpResponse.getStatus(); //获取响应码
        if (status != HttpStatus.HTTP_OK) {
            data.put("error_code",20);
            data.put("description","服务商接口请求失败");
            data.put("ext_order_id",orderSn);
            res.put("data", data);
            return res;
        }
        // 响应结果
        String body = httpResponse.body(); //获取响应内容
        Map<String, Object> map = JSONUtil.parseObj(body);
        if ((int) map.get("code") != 0) {
            data.put("error_code",20);
            data.put("description","服务商接口请求失败");
            data.put("ext_order_id",orderSn);
            res.put("data", data);
            return res;
        }
        List<String> codes = (List<String>)map.get("codes");
//        List<String> qrcodes = (List<String>)map.get("qrcodes");
//
//        List<CodeInfo> codeInfos = IntStream.range(0, codes.size())
//                .mapToObj(i -> {
//                    CodeInfo codeInfo = new CodeInfo();
//                    codeInfo.setCode(codes.get(i));
//                    codeInfo.setCode_redirect(codes.get(i));
//                    return codeInfo;
//                })
//                .collect(Collectors.toList());
        data.put("description","success");
        data.put("error_code",0);
        data.put("result",1);
        data.put("codes",codes);
        res.put("data",data);
        return res;
    }

    @Override
    public Map<String, Object> refund(Map<String, Object> params) {
        Map<String, Object> res = new HashMap<>();
        // 拼接请求服务数据
        Map<String, Object> req = new HashMap<>();
        String orderSn = (String) params.get("order_id");
        req.put("orderId", redisUtils.get(orderSn));
        req.put("orderSn", orderSn);

        List<Map<String, Object>> certificates = (List<Map<String,Object>>) params.get("certificates");
        List<String> voucherList = new ArrayList<>();
        for (Map<String, Object> certificate : certificates) {
            voucherList.add(certificate.get("code").toString());
        }
        req.put("voucherList", voucherList);
        req.put("createUserId", 12);
        // 请求三方接口
        HttpResponse httpResponse = HttpRequest.post(syncUrl + refundUrl)
                .body(JSONUtil.toJsonStr(req))
                .execute();
        logger.info("退款返回：" + httpResponse.getStatus());
        logger.info("body:"+httpResponse.body());
        int status = httpResponse.getStatus(); //获取响应码
        if (status != HttpStatus.HTTP_OK) {
            RefundResponseData outDto = new RefundResponseData();
            outDto.setError_code(-1l);
            outDto.setDescription("商家处理异常！");
            outDto.setResult(2);
            outDto.setReason("商家处理异常！");
            res.put("data", outDto);
            return res;
        }
        // 响应结果
        String body = httpResponse.body(); //获取响应内容
        Map<String, Object> map = JSONUtil.parseObj(body);
        if ((int) map.get("code") != 0) {
            RefundResponseData outDto = new RefundResponseData();
            outDto.setError_code(0L);
            outDto.setDescription("商家处理异常！");
            outDto.setResult(2);
            outDto.setReason("商家处理异常！");
            res.put("data", outDto);
            outDto.setCodes(voucherList);
            logger.info("返回抖音："+JSON.toJSONString(res));
            return res;
        }
        RefundResponseData outDto = new RefundResponseData();
        outDto.setError_code(0l);
        outDto.setDescription("success");
        outDto.setResult(1);
        outDto.setCodes(voucherList);
        res.put("data", outDto);
        logger.info("退票成功后通知抖音："+JSON.toJSONString(res));
        return res;
    }

    @Override
    public Map<String, Object> notify(Map<String,Object> params) {
        return null;
    }

    @Override
    public Map<String, Object> verify(Map<String,Object> params) {

        Map<String, Object> res = new HashMap<>();
        res.put("code",0);
        res.put("msg","检票成功");
        Map<String, Object> req = new HashMap<>();
        req.put("verify_token", System.currentTimeMillis()+"");
        req.put("poi_id","7186648693573945401");
        Set<JSONObject> voucherList = new HashSet<>();
        JSONObject codeObj = new JSONObject();
        codeObj.put("code","YZMNT01520032310305336");
        codeObj.put("verify_time",System.currentTimeMillis());
        voucherList.add(codeObj);
        req.put("code_with_time_list",voucherList);
        req.put("order_id","10133119155392268961");
        HttpResponse httpResponse = HttpRequest.post("https://open.douyin.com/goodlife/v1/fulfilment/certificate/verify/")
                .header("access-token","douyin.N9Wbgp6gjzpcqEEt7rp8CQVyARoHGyWqOigdfZEKbpcEBp2yXP3tZi9BOQ77")
                .header("x-sandbox-token","1")
                .body(JSONUtil.toJsonStr(req))
                .execute();
        int status = httpResponse.getStatus();
        if(status!=200){
            res.put("msg","抖音验券失败");
            res.put("code",1);
            return res;
        }
        String body = httpResponse.body();
        JSONObject bodyRes = JSON.parseObject(body);
        JSONObject dataRes = bodyRes.getJSONObject("data");
        if(dataRes.getInteger("error_code")!=0){
            res.put("code",1);
            res.put("msg",dataRes.getString("description"));
            return res;
        }
        JSONArray result = dataRes.getJSONArray("verify_results");
        JSONObject hxr = result.getJSONObject(0);
        if(hxr.getInteger("result")!=0){
            res.put("msg",hxr.getString("msg"));
            res.put("code",1);
            return res;
        }
        return res;
    }
//    public Map<String, Object> verify(GoodlifeV1FulfilmentCertificateVerifyRequest inDto) {
//        Map<String, Object> res = new HashMap<>();
//        Data data = new Data();
//        String accessToken = getAccessToken();
//        if(StringUtils.isEmpty(accessToken)) {
//            data.setError_code(-1L);
//            data.setDescription("accessToken获取失败");
//            data.setResult(-1);
//            res.put("data", data);
//            return res;
//        }
//        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
//                .setAccessToken(accessToken)
//                .build();
//        try {
//            System.out.println("核销收到参数：" + JSON.toJSONString(inDto));
//            GoodlifeV1FulfilmentCertificateVerifyResponse response = client.execute(inDto);
//            com.kuaishou.locallife.open.api.domain.locallife_trade.Data resData = response.getData();
//            boolean flg = resData.getError_code() == 0 && CollectionUtil.isNotEmpty(resData.getVerify_results()) && resData.getVerify_results().get(0).getResult() == 0L;
//
//            if(flg) {
//                data.setError_code(0L);
//                data.setDescription("success");
//                data.setResult(0);
//            } else {
//                // 处理异常
//                data.setError_code(-1L);
//                data.setDescription(resData.getDescription());
//                data.setResult(-1);
//            }
//            res.put("data", data);
//            return res;
//        } catch (KsLocalLifeApiException e) {
//            // 处理异常
//            data.setError_code(-1L);
//            data.setDescription("快手验券api请求失败");
//            data.setResult(-1);
//            res.put("data", data);
//            return res;
//        }
//    }

    private String getAccessToken() {

        String accessToken = "";
        // 校验redis中是否存在access_token
        System.out.println("==="+redisUtils.get("ACCESS_TOKEN"));
        if (ObjectUtil.isEmpty(redisUtils.get("ACCESS_TOKEN"))) {// 获取access_token
            // 如果有refresh_token就用refresh_token获取，没有就重新获取
            if (ObjectUtil.isNotEmpty(redisUtils.get("REFRESH_TOKEN"))) {
                OAuthAccessTokenKsClient client = new OAuthAccessTokenKsClient(appKey, appSecret);
                String refreshToken = String.valueOf(redisUtils.get("REFRESH_TOKEN"));
                KsAccessTokenPreviousVersionResponse response = null;
                try {
                    response = client.refreshAccessToken(refreshToken);
                } catch (KsLocalLifeApiException e) {}
                // 结果验证
                if(response.getResult() == 1) {// 成功
                    accessToken = response.getAccessToken();
                    long expiresIn = response.getExpiresIn();
                    redisUtils.set("ACCESS_TOKEN", accessToken, expiresIn, TimeUnit.SECONDS);
                }
            } else {
                OAuthAccessTokenKsClient client = new OAuthAccessTokenKsClient(appKey, appSecret);
                try {
                    KsAccessTokenPreviousVersionResponse response = client.getAccessToken(code);
                    if(response.getResult() == 1) {
                        accessToken = response.getAccessToken();
                        String refreshToken = response.getRefreshToken();
                        redisUtils.set("ACCESS_TOKEN", accessToken, response.getExpiresIn(), TimeUnit.SECONDS);
                        redisUtils.set("REFRESH_TOKEN", refreshToken, response.getRefreshTokenExpiresIn(), TimeUnit.SECONDS);
                    }
                } catch (KsLocalLifeApiException e) {}
            }
        } else {
            accessToken = String.valueOf(redisUtils.get("ACCESS_TOKEN"));
        }

        return accessToken;

    }

    private String decrypt(String cipherTxt) {
        String accessToken = getAccessToken();
        if (StringUtils.isEmpty(accessToken)) {
            return StringUtil.EMPTY_STRING;
        }

        KsLocalLifeAccessTokenClient client = KsLocalLifeAccessTokenClient.Builder.newBuilder()
                .setAccessToken(accessToken)
                .build();

        GoodlifeSecurityDecryptBatchRequest request = new GoodlifeSecurityDecryptBatchRequest();

        List<CipherInfoRequest> list1 = new ArrayList<>();
        CipherInfoRequest obj1 = new CipherInfoRequest();
        obj1.setCipher_text(cipherTxt);
        list1.add(obj1);
        request.setCipher_infos(list1);

        try {
            GoodlifeSecurityDecryptBatchResponse response = client.execute(request);
            if (ObjectUtil.isEmpty(response.getData()) || response.getData().getError_code() != 0) {
                return StringUtil.EMPTY_STRING;
            }
            List<CipherInfoResponse> cipherInfos = response.getData().getCipher_infos();
            if(CollectionUtil.isEmpty(cipherInfos)) {
                return StringUtil.EMPTY_STRING;
            }
            return cipherInfos.get(0).getDecrypt_text();
        } catch (KsLocalLifeApiException e) {
            // 处理异常
            return StringUtil.EMPTY_STRING;
        }
    }

}
